<?php
/**
  * Invision Power Board <= 3.3.4 "unserialize()" PHP Code Execution漏洞成因代码简化版
  * @link http://www.exploit-db.com/exploits/22398/
  * @version $Id: index.php 219 2012-11-04 06:17:33Z horselukeCN@gmail.com $
  */
  

/**
  * one_class（含有完整功能的示例类）
  */
class one_class{

	/**
	  * 随机分配的运行id
	  * @var int
	  */
	private $id = 0;
	
	/**
	  * 版本号（PHP 5设置属性为公有访问的写法）
	  * @var string
	  * @access public
	  */
	public $version = '1.0';
	
	/**
	  * 调试模式？（PHP 4属性写法，均为公有访问）
	  * @var string
	  * @access public
	  */	
	var $debug = false;
	
	
	/**
	  * 魔术方法：创建类实例时调用
	  * @return one_class
	  */
	public function __construct(){
		$this->id = mt_rand(1, 100000);
		echo "[id:{$this->id}]". '__construct >>>>>> Version:'. $this->version. "\r\n";
	}
	
	/**
	  * 魔术方法：unserialize()调用的方法，按照手册说法，用于“预先准备对象数据”。 
	  */	
	public function __wakeup(){
		echo "[id:{$this->id}]". '__wakeup >>>>>> Version:'. $this->version. "\r\n";
	}
	
	/**
	  * 魔术方法：对象被销毁前所调用方法 
	  */		
	public function __destruct(){
		if(true === $this->debug){
			echo "[id:{$this->id}]". '__destruct >>>>>> Version:'. $this->version. ' Writing Log...'. "\r\n";
		}else{
			echo "[id:{$this->id}]". '__destruct >>>>>> Version:'. $this->version. ' Ignore Log...'. "\r\n";
		}
	}
	
}

echo "\r\n//////normal_class_var DEMO BEGIN.//////\r\n";
/**
  * 正常的、不修改任何属性的类，其活动轨迹为__construct()和__destruct()
  * 所以，随机分配的运行id必为大于0的值，并且debug状态为false
  */
$normal_class_var = new one_class();
var_dump($normal_class_var);
echo "\r\n//////normal_class_var DEMO FINISH...REALLY FINISH?!//////\r\n\r\n\r\n";


/**
  * unserialize时，并不会调用__construct()，而会调用__wakeup()，这导致随机分配的运行id必等于0的值
  * $exp_serialized_data则演示了，如何通过unserialize修改公有属性，从而产生debug被打开，并在后续进行__destruct时触发漏洞。
  * $exp_serialized_data的内容获取方法请参考index_harm.php
  * @var string
  */
$exp_serialized_data = 'O:9:"one_class":2:{s:7:"version";s:5:"999.0";s:5:"debug";b:1;}';

echo "\r\n//////exp_serialized_data DEMO BEGIN.//////\r\n";
$exp_serialized_data = unserialize($exp_serialized_data);
var_dump($exp_serialized_data);
echo "\r\n//////exp_serialized_data DEMO FINISH...REALLY FINISH?!//////\r\n\r\n\r\n";